package bosc.cn.service.payment.impl;

import bosc.cn.constant.ApplyConstants;
import bosc.cn.constant.BusinessConstants;
import bosc.cn.dto.common.CommonRequest;
import bosc.cn.dto.common.CommonResponse;
import bosc.cn.dto.common.RequestWrapper;
import bosc.cn.dto.common.ResponseWrapper;
import bosc.cn.service.payment.PaymentConfirmService;
import bosc.cn.service.payment.bo.PaymentConfirmReqBO;
import bosc.cn.service.payment.bo.PaymentConfirmResBO;
import bosc.cn.util.SerialNoGenerator;
import client.SignClient;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import dto.VerifyRequest;
import dto.VerifyResponse;
import lombok.extern.slf4j.Slf4j;
import mapper.BusinessInfoMapper;
import mapper.UserInfoMapper;
import mapper.WalletInfoMapper;
import mapper.WalletUserInfoMapper;
import model.BusinessInfo;
import model.WalletInfo;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.UUID;

import static bosc.cn.util.SerialNoGenerator.generateCnsmrSrlNo;

@Slf4j
@Service
public class PaymentConfirmServiceImpl implements PaymentConfirmService {

    @Autowired
    private BusinessInfoMapper businessInfoMapper;

    @Autowired
    private WalletInfoMapper walletInfoMapper;

    @Autowired
    private WalletUserInfoMapper walletUserInfoMapper;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private SignClient signClient;

    // 银行内部户
    private static final String INTERNAL_WALLET_ID = "BANK_INTERNAL";

    @Override

    public ResponseWrapper<PaymentConfirmResBO> confirmPayment(PaymentConfirmReqBO reqBO) {

        ResponseWrapper<PaymentConfirmResBO> resBO = new ResponseWrapper<>();
        CommonResponse head = new CommonResponse();
        PaymentConfirmResBO body = new PaymentConfirmResBO();


        try {

            // 正常通信
            head.setRetCd("000000");
            head.setRetMsg("通信成功");
            head.setRetTm(LocalDateTime.now());

            // 申请单号不能为空
            if (StringUtils.isBlank(reqBO.getApplyNo())) {
                body.setPrcSts("PR99");
                body.setPrcMsg("申请单号不能为空");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }
            // 转出/转入钱包判空校验参数
            if (reqBO.getTfrOutWltId() == null || reqBO.getTfrOutWltId().trim().isEmpty()) {
                body.setPrcSts("PR99");
                body.setPrcMsg("转出钱包ID不能为空");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            if (reqBO.getTfrInWltId() == null || reqBO.getTfrInWltId().trim().isEmpty()) {
                body.setPrcSts("PR88");
                body.setPrcMsg("转入钱包ID不能为空");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            // 查询转出/转入钱包
            WalletInfo outWallet = walletInfoMapper.selectOne(
                    new LambdaQueryWrapper<WalletInfo>()
                            .eq(WalletInfo::getWltId, reqBO.getTfrOutWltId())
            );

            if (outWallet == null) {
                body.setPrcSts("PR77");
                body.setPrcMsg("转出钱包不存在");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            WalletInfo inWallet = walletInfoMapper.selectOne(
                    new LambdaQueryWrapper<WalletInfo>()
                            .eq(WalletInfo::getWltId, reqBO.getTfrInWltId())
            );

            if (inWallet == null) {
                body.setPrcSts("PR66");
                body.setPrcMsg("转入钱包不存在");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            // 查找内部户
            WalletInfo internalWallet = walletInfoMapper.selectOne(
                    new LambdaQueryWrapper<WalletInfo>()
                            .eq(WalletInfo::getWltId, INTERNAL_WALLET_ID)
            );

            // 校验余额是否足够
            BigDecimal amount = reqBO.getTxnAmt();
            if (outWallet.getWltBal().compareTo(amount) < 0) {
                body.setPrcSts("PR55");
                body.setPrcMsg("转出钱包余额不足");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            // 校验共同授权信息
            if (reqBO.getAuthInfo() == null || reqBO.getAuthInfo().trim().isEmpty()) {
                body.setPrcSts("PR44");
                body.setPrcMsg("共同授权信息不能为空");
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            // 全局流水号
            String glblSrlNo = SerialNoGenerator.generateGlblSrlNo("1001"); // 渠道号
            // 构造请求头
            CommonRequest requestHead = new CommonRequest();
            requestHead.setGlblSrlNo(glblSrlNo);   // 透传 bank-service 的全局流水号
            requestHead.setCnsmrSrlNo(generateCnsmrSrlNo("2002"));
            requestHead.setTxnTm(LocalDateTime.now());

            // 封装验签请求
            VerifyRequest verifyRequest = new VerifyRequest();
            verifyRequest.setAuthMsg(reqBO.getAuthMsg());
            verifyRequest.setAuthInfo(reqBO.getAuthInfo());
            verifyRequest.setAuthList(reqBO.getAuthList());
            verifyRequest.setWltId(reqBO.getTfrOutWltId());

            // 调用 sign-service 的 verify 接口
            RequestWrapper<VerifyRequest> wrapper = new RequestWrapper<>();
            wrapper.setHead(requestHead);
            wrapper.setBody(verifyRequest);

            ResponseWrapper<VerifyResponse> verifyResponse = signClient.verify(wrapper);
//            VerifyResponse verifyResponse = signClient.verify(verifyRequest);
            System.out.println("<<<< 调用 sign-service.verify 返回结果: " + verifyResponse);
            if (!"PR00".equals(verifyResponse.getBody().getPrcSts())) {
                body.setPrcSts(verifyResponse.getBody().getPrcSts());
                body.setPrcMsg("验签失败：" + verifyResponse.getBody().getPrcMsg());
                resBO.setHead(head);
                resBO.setBody(body);
                return resBO;
            }

            // 转出钱包扣款 → 内部户
            outWallet.setWltBal(outWallet.getWltBal().subtract(amount));
            outWallet.setLastUpdateTime(LocalDateTime.now());
            outWallet.setLastUpdateOperate("支付确认：转出钱包扣款");

            // 内部户入账
            internalWallet.setWltBal(internalWallet.getWltBal().add(amount));
            internalWallet.setLastUpdateTime(LocalDateTime.now());
            internalWallet.setLastUpdateOperate("支付确认：内部户入账");

            // 内部户转出 -> 转入钱包收款
            internalWallet.setWltBal(internalWallet.getWltBal().subtract(amount));
            inWallet.setWltBal(inWallet.getWltBal().add(amount));
            inWallet.setLastUpdateTime(LocalDateTime.now());
            inWallet.setLastUpdateOperate("支付确认：转入钱包收款");

            // 更新数据库
            walletInfoMapper.updateById(outWallet);
            walletInfoMapper.updateById(internalWallet);
            walletInfoMapper.updateById(inWallet);

            // 记录业务流水写入 business_info 表
            BusinessInfo businessInfo = new BusinessInfo();

            // 业务流水号
            String agentSerialNo = UUID.randomUUID().toString().replace("-", "").substring(0, 28);
            businessInfo.setAgentSerialNo(agentSerialNo);

            // 全局流水号、消费方流水号
//            String glblSrlNo = SerialNoGenerator.generateGlblSrlNo("1001"); // 渠道号
            String cnsmrSrlNo = generateCnsmrSrlNo("2002"); // 系统号
            businessInfo.setGlblSrlNo(glblSrlNo);
            businessInfo.setCnsmrSrlNo(cnsmrSrlNo);

            // 申请单号,上有补送
            businessInfo.setApplyNo(reqBO.getApplyNo());

            // 转账申请
            businessInfo.setApplyTp(ApplyConstants.ApplyType.TRANSFER);

            // 通过转出钱包ID在领用记录表中查找对应的用户信息
            // 申请人id 上游送
            businessInfo.setUserId(reqBO.getApplyUserId());

            businessInfo.setTfrOutWltId(reqBO.getTfrOutWltId());
            businessInfo.setTfrOutWltNm(reqBO.getTfrOutWltNm());
            businessInfo.setTfrInWltId(reqBO.getTfrInWltId());
            businessInfo.setTfrInWltNm(reqBO.getTfrInWltNm());

            // 经办人信息
            businessInfo.setOprIdentTp(reqBO.getOprIdentTp());
            businessInfo.setOprIdentNo(reqBO.getOprIdentNo());
            businessInfo.setOprNm(reqBO.getOprNm());
            businessInfo.setOprTelNo(reqBO.getOprTelNo());

            // 交易信息
            businessInfo.setTxnSmy(reqBO.getTxnSmy());
            businessInfo.setTxnAmt(reqBO.getTxnAmt());
            businessInfo.setTfrInTel(reqBO.getTfrInTel());

            // 审批授权信息
            businessInfo.setAuthList(
                    String.join(",", reqBO.getAuthList())
            );
            businessInfo.setAuthInfo(reqBO.getAuthInfo());
            businessInfo.setAuthMsg(reqBO.getAuthMsg());

            // 交易成功
            businessInfo.setTxnSts(BusinessConstants.TxnStatus.SUCCESS);
            businessInfo.setCreateTime(LocalDateTime.now());
            businessInfo.setLastUpdateTime(LocalDateTime.now());
            businessInfo.setLastUpdateOperate("支付确认交易成功");

            // 插入交易流水表
            businessInfoMapper.insert(businessInfo);


            // 封装响应
            body.setPrcSts("PR00");
            body.setPrcMsg("支付确认成功");

        } catch (Exception e) {
            log.error("支付确认异常：" + e.getMessage(), e);
            // 出现异常，通信失败
            head.setRetCd("999999");
            head.setRetMsg("系统异常：" + e.getMessage());
            head.setRetTm(LocalDateTime.now());
        }

        resBO.setHead(head);
        resBO.setBody(body);
        return resBO;
    }

}
